﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows;

namespace PDX.Notification
{
    /// <summary>
    /// A basic implementation of a <see cref="INotificationManager"/>
    /// </summary>
    public class BasicNotificationManager : INotificationManager
    {
        /// <summary>
        /// Transactionally raises the <see cref="NotificationRaised"/> event.
        /// </summary>
        public void Notify()
        {
            using (BeginDisposableTransaction())
            {
            }
        }

        void NotifyCore()
        {
            var temp = IsTransactionInProgress;
            IsTransactionInProgress = true;
            try
            {
                NotificationRaised(this, EventArgs.Empty);
            }
            finally
            {
                IsTransactionInProgress = temp;
            }
        }

        /// <summary>
        /// Signal to subscribers that state may have changed.
        /// For example, property values on the viewmodel.
        /// </summary>
        public event EventHandler NotificationRaised = delegate { };

        /// <summary>
        /// Gets a value indicating whether there is transaction in progress.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if there is transaction in progress; otherwise, <c>false</c>.
        /// </value>
        public bool IsTransactionInProgress { get; private set; }

        /// <summary>
        /// Gets the transaction number.
        /// This is incremented every transaction.
        /// </summary>
        public int TransactionNumber { get; private set; }


        /// <summary>
        /// Begins a disposable transaction.
        /// Clients will probably want to use a "using" statement.
        /// </summary>
        /// <returns></returns>
        public Transaction BeginDisposableTransaction()
        {
            bool isOutermostTransaction = !IsTransactionInProgress;

            IsTransactionInProgress = true;
            var transaction = new Transaction();

            if (isOutermostTransaction)
            {
                TransactionNumber++;
                transaction.Completed += transaction_Completed;
            }

            return transaction;
        }

        void transaction_Completed(object sender, EventArgs e)
        {
            NotifyCore();
            IsTransactionInProgress = false;
        }
    }
}
